from django import forms
from django.contrib.auth.models import Group
from posecco.models import RFC, WorkOrder, User, Infrastructure, Service
from posecco.widgets import SpanWidget
import posecco.models

"""
Method that sets fields to span field and sets value to string for choicefields
"""
def set_fields(form, instance, fields):
    for field in fields:
        form.fields[field].widget = SpanWidget()
        #get_name_display is methodname of choice, so if it exists, it is a choice field
        if hasattr(instance, 'get_%s_display' % field):
            #set value to string of choice
            form.fields[field].widget.set_value(getattr(instance, 'get_%s_display' % field)())
        #if field is a foreignkey field_id exists, so if foreign key, use str method on item
        elif hasattr(instance, '%s_id' % field) and hasattr(getattr(instance, field), "id"):
            form.fields[field].widget.set_value(str(getattr(instance, field)), getattr(instance, field).id)
        #if field type is manyrelatedmanager, it is manytomanyfield so then display list of all items
        elif 'ManyRelatedManager' in str(type(getattr(instance, field))):
            values = [str(value) for value in getattr(instance, field).all()]
            actualvalues = [value['id'] for value in getattr(instance, field).values()]
            if len(values) > 0:
                vstring = ', '.join(values)
            else:
                vstring = ''
            form.fields[field].widget.set_value(vstring, actualvalues, True)

#static reference to groups (so query has only to run once)
sysadmin = Group.objects.get(name="System Administrator")
change_manager = Group.objects.get(name="Change Manager")
approver = Group.objects.get(name="Approver")
cms_user = Group.objects.get(name="CMS User")

class RFCForm(forms.ModelForm):
    class Meta:
        model = RFC
    
    def clean(self):
        cleaned_data = super(RFCForm, self).clean()
        status = cleaned_data.get("status")
        owner = cleaned_data.get("owner")

        if status == 2: #only change manager or system administrator may change the status after it's approved
            # Only do something if both fields are valid so far.
            if owner is None:
                raise forms.ValidationError("Please choose an owner for this RFC.")

        # Always return the full collection of cleaned data.
        return cleaned_data

    def set_formfields(self, user, rfc):
            
        #hide all fields by default
        fields = ['summary', 'description', 'services', 'infrastructure', 'status', 'owner', 'priority']
        if rfc.pk > 0: #everyone can create an rfc
            if rfc.status == 2 and change_manager in user.groups.all(): #only change manager or system administrator may change the status after it's approved
                fields = ['status']
            elif rfc.status == 3 and approver in user.groups.all():
                fields = ['status', 'summary', 'description', 'services', 'infrastructure', 'owner', 'priority']
        else:
            fields = ['status']
        set_fields(self, rfc, fields)


class WorkOrderForm(forms.ModelForm):
    class Meta:
        model = WorkOrder
        
    def clean(self):
        cleaned_data = super(WorkOrderForm, self).clean()
        status = cleaned_data.get("status")
        responsible = cleaned_data.get("responsible")
        wo_type = cleaned_data.get("workOrderType")

        if status == 1: #only change manager or system administrator may change the status after it's approved
            # Only do something if both fields are valid so far.
            if responsible is None:
                raise forms.ValidationError("Please choose a responsible for this work order.")

            if wo_type < 1:
                raise forms.ValidationError("Please choose a work order type for this work order.")

        # Always return the full collection of cleaned data.
        return cleaned_data

    def set_formfields(self, user, workorder):
        fields = ['rfc', 'plannedStart', 'plannedEnd', 'actualStart', 'actualEnd', 'workOrderType', 'responsible', 'description', 'affectedServices', 'affectedInfrastructure', 'plannedEffort', 'status']
        
        if workorder.status == 1 and approver in user.groups.all():
            fields = ['rfc', 'status', 'actualStart', 'actualEnd']
        if workorder.status == 2 and workorder.responsible == user:
            fields = ['rfc', 'status', 'plannedStart', 'plannedEnd', 'workOrderType', 'responsible', 'affectedServices', 'affectedInfrastructure', 'plannedEffort']
        
        set_fields(self, workorder, fields)


class UserForm(forms.ModelForm):
    class Meta:
        model = User
        
    def set_formfields(self, user, userobj):  
        fields = ['password']
        if sysadmin not in user.groups.all():
            for field in self.fields:
                if field.fieldname != 'password':
                    fields.append(field)
        
        set_fields(self, userobj, fields)


class ExportForm(forms.Form):
    empty_option = [['', '----------']]
    status_choices = empty_option
    status_choices += posecco.models.status_choices
    priority_choices = empty_option
    priority_choices += posecco.models.priority_choices
    services = forms.ModelChoiceField(queryset=Service.objects.all())
    infrastructure = forms.ModelChoiceField(queryset=Infrastructure.objects.all())
    status = forms.TypedChoiceField(choices=status_choices)
    owner = forms.ModelChoiceField(queryset=User.objects.all())
    initiator = forms.ModelChoiceField(queryset=User.objects.all())
    priority = forms.ChoiceField(choices=priority_choices)


class InfrastructureForm(forms.ModelForm):
    class Meta:
        model = Infrastructure
        
    def set_formfields(self, user, infrastructure):
        fields = []
        
        set_fields(self, infrastructure, fields)

class ServiceForm(forms.ModelForm):
    class Meta:
        model = Service
        
    def set_formfields(self, user, service):
        fields = []
        
        set_fields(self, service, fields)

class UploadForm(forms.Form):
    file = forms.FileField()
